Skip to content

COR-1258: generate CycloneDX SBOMs alongside scan reports - #142

Open
juangaitanv wants to merge 7 commits into
mainfrom
juan/cor-1258
Open

COR-1258: generate CycloneDX SBOMs alongside scan reports#142
juangaitanv wants to merge 7 commits into
mainfrom
juan/cor-1258

Conversation

@juangaitanv

Copy link
Copy Markdown
Contributor

Summary

Implements COR-1258: generate a CycloneDX (1.7, latest) SBOM immediately after a scan, alongside the SARIF report.

  • New corgea scan --sbom [FILE] flag (default bom.json): after the blast scan completes and any --out-format report is written, a CycloneDX SBOM is generated locally from the project tree via the offline deps engine — no server changes, no network.
  • CycloneDX emitter upgraded from bare 1.4 to spec 1.7: serialNumber (urn:uuid), metadata (timestamp, tool, root component), bom-ref on every component, dependsOn grouped per ref. Output validates against the official bom-1.7.schema.json; corgea deps sbom shares the same emitter.
  • Maven: ${property} / ${project.version} version placeholders now resolve before purl construction, and the scanner emits root→dependency edges (the dependencies array was always empty for pure-Maven projects).
  • Detected-but-unsupported ecosystems (Go, Cargo) now print a stderr warning instead of silently producing an empty-looking SBOM.
  • deps subcommands error cleanly (exit 2) on nonexistent paths instead of succeeding with empty output.

Compliance enrichment (licenses, scope, hashes, Go/Cargo coverage) is tracked separately in COR-1733.

Test plan

  • cargo test — 543 passed, 0 failed (clippy clean, fmt clean)
  • New e2e test tests/cli_scan_sbom.rs: full stubbed scan flow → default bom.json, custom filename, no file without the flag
  • Maven property/edge coverage in maven_tests.rs + new java-maven-props fixture
  • Ecosystem-warning + nonexistent-path CLI tests in cli_deps.rs
  • Generated SBOMs validated against the official CycloneDX 1.7 JSON schema (npm + Maven fixtures)
  • 5-scenario agent test sweep: 48/50 checks passing before these fixes; the 2 failures are addressed here

Add `corgea scan --sbom [FILE]` (default bom.json): after a blast scan
completes, generate a CycloneDX SBOM locally from the project tree via
the offline deps engine, alongside any --out-format report.

- Upgrade the CycloneDX emitter from bare 1.4 to spec 1.7: serialNumber,
  metadata (timestamp, tool, root component), bom-refs on components,
  dependsOn grouped per ref. Output validates against the official
  bom-1.7 JSON schema.
- Maven: resolve ${property} / ${project.version} version placeholders
  and emit root->dependency graph edges (dependencies array was always
  empty for pure-Maven projects).
- Warn on stderr when detected ecosystems (Go, Cargo) are not included
  in the SBOM, instead of silently emitting an empty-looking document.
- Error cleanly (exit 2) on nonexistent paths in deps subcommands.
- Tests: e2e scan --sbom against the HTTP stub, Maven property/edge
  coverage, warning + path-error CLI tests, emitter unit tests. Scrub
  GIT_* env in the repo-info test so it passes inside git hooks.
Comment thread src/deps/report.rs Outdated
Comment thread src/deps/report.rs Outdated
Comment thread src/deps/ecosystems/maven.rs
Comment thread src/scanners/blast.rs Outdated
…inherited-version deps

- Omit component version/purl when the version is unresolved (? placeholder
  or ${...} Maven property) instead of emitting null versions and invalid
  @? purls; bom-ref keeps the internal id.
- Dedup components by bom-ref and dependsOn per ref (schema uniqueItems).
- Maven: project.version falls back to the parent's version for child POMs
  and resolves through properties (${revision} CI versioning).
- scan --sbom write failures exit 1 with a clean error instead of panicking.

All emitter outputs re-validated against the official bom-1.7 schema.
Comment thread src/deps/ecosystems/maven.rs
Comment thread src/deps/ecosystems/maven.rs
Test added 2 commits July 30, 2026 13:51
unsupported_ecosystem_label re-encoded which ecosystems produce graph
nodes; derive it from ecosystems::is_graphed, defined beside the scanner
dispatch so a future Go/Cargo scanner updates both in one place.
- dependencyManagement entries no longer emit components/edges; their
  versions fill versionless direct declarations in the same POM.
- Property values resolve to a fixed point (bounded, cycle-safe) so
  chained ${...} references fully substitute.
- Empty versions count as unresolved in the SBOM emitter (no bare @ purls).

Parent/imported BOM resolution stays deferred to COR-1733.
Comment thread src/deps/report.rs Outdated
Comment thread src/deps/ecosystems/maven.rs Outdated
Comment thread src/deps/ecosystems/maven.rs Outdated
Comment thread src/deps/report.rs Outdated
Comment thread src/deps/ecosystems/maven.rs Outdated
Test added 2 commits July 30, 2026 16:23
…lution

- to_cyclonedx filters the synthetic root by id, not display name, so a
  real package named 'root' keeps its component (no dangling dependsOn).
- pom_project_version stops at the first nested section
  (dependencyManagement/build/reporting/profiles) so plugin versions can't
  hijack ${project.version}; parent fallback unchanged.
- Property fixed-point resolution re-runs after project.version is
  inserted so properties aliasing ${project.version} resolve.
split_dependency_management and pom_project_version's parent handling
used the same find-open/find-close/remove-section scanning; extract it
into split_section. Compare the synthetic root via PackageId::root()
instead of a raw string literal, matching the rest of the codebase.

@corgea-security corgea-security left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review risk: 4/5.

The SBOM can silently contain false Maven dependencies or omit resolvable versions because parsing remains structurally overbroad and property resolution is arbitrarily capped.

Critical or high-priority changes must be addressed.

Automatic approval was not submitted: automated review found critical or high-priority findings.

@corgea-security corgea-security added the dennis-reviewed Dennis completed an automated review label Jul 30, 2026
…ution

- Strip <profiles> and <build> sections before dependency extraction so
  plugin dependencies and profile dependencies no longer surface as
  application dependencies in the graph/SBOM.
- Bound the property fixed-point loop by the property count instead of a
  fixed 5: a chain can't be longer than the map without a cycle.
@juangaitanv

Copy link
Copy Markdown
Contributor Author

Re the automated risk-4 review (no inline findings attached): both concerns it gestures at are now addressed in 7e5c718.

  • Structural overbreadth: <build> (plugin dependencies) and <profiles> sections are stripped before dependency extraction, alongside the existing <dependencyManagement> handling — plugin/profile deps no longer surface as application dependencies. Verified with a fixture carrying both; only the real dependency lands in the SBOM.
  • Arbitrary resolution cap: the property fixed-point loop is now bounded by the property count (a chain cannot be longer than the map without a cycle) instead of a fixed 5, with a 7-level-chain regression test.

Remaining Maven gaps (parent POM chains, imported BOMs, profile activation) are effective-POM resolution, deliberately out of scope here and tracked in COR-1733.

@juangaitanv
juangaitanv requested a review from yhoztak July 31, 2026 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dennis-reviewed Dennis completed an automated review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants